import asyncio
from threading import Thread

import serial
import serial.tools.list_ports
from src.lib.errorno import g_errno_d
from src.module.serial_asyncio import create_serial_connection


class PortEvet(asyncio.Protocol):
    ''' 定义异步串口回调事件类 '''
    def __init__(self):
        super().__init__()
        self._transport = None

    def connection_made(self, transport):
        self._transport = transport

    def data_received(self, data):
        self.rx_callback(data)

    def connection_lost(self, exc):
        self._transport.loop.stop()
        self.err_callback("MSG:close")

    def pause_writing(self):
        self.err_callback("MSG:busy0")

    def resume_writing(self):
        self.err_callback("MSG:busy1")

    def rx_callback(self, data):
        pass

    def err_callback(self, msg):
        pass


class AsyncioPort():
    ''' 定义异步串口功能类 '''
    m_i_first_start = 0

    def __init__(self, rx_callback, err_callback):
        super(AsyncioPort, self).__init__()
        self.rx_callback = rx_callback
        self.err_callback = err_callback

    def getPortList(self):
        port_list = serial.tools.list_ports.comports()
        com_list = []
        for port in port_list:
            str_s = port[0] + " " + (port[1].split("(")[0])
            com_list.append(str_s)
        return com_list

    def open(self, port, baudrate):
        try:
            '''新建串口事件'''
            self.loop = asyncio.new_event_loop()
            self.coro = create_serial_connection(self.loop,
                                                 PortEvet,
                                                 (port.split(" ")[0]),
                                                 baudrate=baudrate)
            asyncio.set_event_loop(self.loop)
            self.transport, self.protocol = self.loop.run_until_complete(self.coro)
            self.protocol.rx_callback = self.rx_callback
            self.protocol.err_callback = self.err_callback
            '''启动循环线程'''
            self.pool = ""
            self.pool = Thread(target=self.run, daemon=True)
            self.pool.start()

        except Exception:
            return g_errno_d['OPEN']
        return g_errno_d['OK']

    def run(self):
        try:
            self.loop.run_forever()
            self.loop.close()  # 关闭循环
        except Exception:
            print("串口事件异常退出")

    # 通过消息队列发送
    def sendMsg(self, data):
        try:
            self.transport.write(data)
        except Exception:
            pass

    # 直接调用串口发送
    def sendMsgReal(self, data):
        try:
            self.transport.serial.write(data)
        except Exception:
            pass

    def close(self):
        try:
            self.transport.close()
        except Exception:
            pass

    def is_closing(self):
        try:
            return self.transport.is_closing()
        except Exception:
            return True